using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Common;
using Google.Protobuf.WellKnownTypes;
using Grpc.Core;
using Microsoft.AspNetCore.Authorization;
using Microsoft.IdentityModel.Tokens;
using User;
using InternalService = inter.InternalService.InternalServiceClient;

public class UserService : LoginService.LoginServiceBase
{
    private readonly InternalService _internalService;
    private readonly IHttpContextAccessor _httpContextAccessor;

    public UserService(InternalService internalService, IHttpContextAccessor httpContextAccessor)
    {
        _internalService = internalService;
        _httpContextAccessor = httpContextAccessor;
    }

    [AllowAnonymous]
    public override Task<LoginResponse> Login(LoginRequest request, ServerCallContext context)
    {
        var token = BuildToken(request);
        return Task.FromResult(new LoginResponse() { Success = true, Token = token });
    }

    [Authorize]
    public override Task<UserProfile> GetProfile(Empty request, ServerCallContext context)
    {
        var username = _httpContextAccessor.HttpContext.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Name);
        return Task.FromResult(new UserProfile() { Username = "aaa", Email = "bbb", Address = "ccc", Age = 0 });
    }

    //[Authorize(Roles = GlobalConst.AdminPolicy)]
    [Authorize(Policy = GlobalConst.AdminPolicy)]
    public override async Task<SafeCallResponse> SafeCall(Empty request, ServerCallContext context)
    {
        var headers = context.RequestHeaders;
        headers.Add("caller-user", Environment.UserName);
        var resp = await _internalService.InternalCallAsync(request, headers);
        return new SafeCallResponse() { HeaderValue = resp.HeaderValue };
    }


    private static readonly JwtSecurityTokenHandler JwtTokenHandler = new JwtSecurityTokenHandler();

    private string BuildToken(LoginRequest request)
    {
        if (string.IsNullOrEmpty(request.Username))
        {
            throw new InvalidOperationException("Name is not specified.");
        }

        var claims = new List<Claim> { new Claim(ClaimTypes.UserData, request.Username) };
        if ("guest".Equals(request.Username))
        {
            claims.Add(new Claim(GlobalConst.RoleClaim, "guest"));
        }

        if ("admin".Equals(request.Username))
        {
            claims.Add(new Claim(GlobalConst.RoleClaim, "admin"));
        }


        var credentials = new SigningCredentials(GlobalConst.SecurityKey, SecurityAlgorithms.HmacSha256);
        var token = new JwtSecurityToken("ExampleServer", "ExampleClients", claims,
            expires: DateTime.Now.AddDays(60),
            signingCredentials: credentials);
        return JwtTokenHandler.WriteToken(token);
    }
}